#include"MsgBuffer.h"
#include <assert.h>
#include <cstring>   // memcpy
#include <sys/uio.h> // readv

#include <algorithm>//std::search


using namespace tmms::network;

MsgBuffer::MsgBuffer(size_t initialSize)
    : buffer_(kCheapPrepend + initialSize),
    readerIndex_(kCheapPrepend),
    writerIndex_(kCheapPrepend)  
{
    assert(readableBytes() == 0);//在调试阶段强制检查程序假设，一旦条件不成立就立即终止并报错
    assert(writableBytes() == initialSize);
    assert(prependableBytes() == kCheapPrepend);
}

MsgBuffer::~MsgBuffer() {}

    
size_t MsgBuffer::readableBytes() const
{
    return writerIndex_ - readerIndex_; 
}

size_t MsgBuffer::writableBytes() const
{
    return buffer_.size() - writerIndex_;
}

size_t MsgBuffer::prependableBytes() const
{
    return readerIndex_;
}

const char* MsgBuffer::peek() const
{
    return begin() + readerIndex_;
}

char* MsgBuffer::beginWrite()
{
    return begin() + writerIndex_;
}

const char* MsgBuffer::beginWrite() const
{
    return begin() + writerIndex_;
}

void MsgBuffer::hasWritten(size_t len)
{//将写的位置后移len
    assert(len <= writableBytes());
    writerIndex_ += len;
}

void MsgBuffer::unwrite(size_t len)
{//将写的位置前移len
    assert(len <= readableBytes());
    writerIndex_ -= len;
}

//retrieve系列函数从readable空间取走数据，只关心移动readableIndex_，改变readable空间大小
void MsgBuffer::retrieve(size_t len)
{
    assert(len <= readableBytes());
    if (len < readableBytes()) // readable 中数据充足时, 只取走len byte数据
    {
        readerIndex_ += len;
    }
    else
    { // readable中数据不足时, 取走所有数据
        retrieveAll();
    }
}

void MsgBuffer::retrieveUntil(const char* end)
{
    assert(peek() <= end);
    assert(end <= beginWrite());
    retrieve(end - peek());
}

void MsgBuffer::retrieveInt64()
{
    retrieve(sizeof(int64_t));
}

void MsgBuffer::retrieveInt32()
{
    retrieve(sizeof(int32_t));    
}

void MsgBuffer::retrieveInt16()
{
    retrieve(sizeof(int16_t));
}

void MsgBuffer::retrieveInt8()
{
    retrieve(sizeof(int16_t));
}

void MsgBuffer::retrieveAll()
{
    readerIndex_ = kCheapPrepend;
    writerIndex_ = kCheapPrepend;   
}

std::string MsgBuffer::retrieveAllAsString()
{
    return retrieveAsString(readableBytes());
}

std::string MsgBuffer::retrieveAsString(size_t len)
{
    assert(len <= readableBytes());
    std::string result(peek(), len);
    retrieve(len);
    return result;
}

int64_t MsgBuffer::readInt64()
{
    int64_t result = peekInt64();
    retrieveInt64();
    return result;
}

int32_t MsgBuffer::readInt32()
{
    int32_t result = peekInt32();
    retrieveInt32();
    return result;
}

int16_t MsgBuffer::readInt16()
{
    int16_t result = peekInt16();
    retrieveInt16();
    return result;
}

int8_t MsgBuffer::readInt8()
{
    int8_t result = peekInt8();
    retrieveInt8();
    return result;
}

int64_t MsgBuffer::peekInt64() const //const对象只能调用const成员函数
{
    //安全地从缓冲区复制一段二进制数据到变量中​​
    assert(readableBytes() >= sizeof(int64_t));
    int64_t be64 = 0;
    ::memcpy(&be64, peek(), sizeof(be64));
    return this->networkToHost64(be64); // 网络字节序转换为本地字节序
}

int32_t MsgBuffer::peekInt32() const
{
    //安全地从缓冲区复制一段二进制数据到变量中​​
    assert(readableBytes() >= sizeof(int32_t));
    int32_t be32 = 0;
    ::memcpy(&be32, peek(), sizeof(be32));
    return networkToHost32(be32); // 网络字节序转换为本地字节序
}

int16_t MsgBuffer::peekInt16() const
{
    //安全地从缓冲区复制一段二进制数据到变量中​​
    assert(readableBytes() >= sizeof(int16_t));
    int16_t be16 = 0;
    ::memcpy(&be16, peek(), sizeof(be16));
    return networkToHost16(be16); // 网络字节序转换为本地字节序
}

int8_t MsgBuffer::peekInt8() const
{ //是按照字节来存储的，8是一个字节  所以就不用转化了
    //安全地从缓冲区复制一段二进制数据到变量中​​
    assert(readableBytes() >= sizeof(int8_t));
    int8_t x = *peek();
    return x;
}

void MsgBuffer::prependInt64(int64_t x)
{
    int64_t be64 = this->hostToNetwork64(x);
    prepend(&be64, sizeof(be64));
}


void MsgBuffer::prependInt32(int32_t x)
{
    int64_t be32 = this->hostToNetwork32(x);
    prepend(&be32, sizeof(be32));
}


void MsgBuffer::prependInt16(int16_t x)
{
    int16_t be16 = this->hostToNetwork16(x);
    prepend(&be16, sizeof(be16));
}

void MsgBuffer::prependInt8(int8_t x)
{
    prepend(&x, sizeof(x));
}


void MsgBuffer::prepend(const void* data, size_t len) //往prepend中写入数据
{
    assert(len <= prependableBytes());
    readerIndex_ -= len;
    const char* d = static_cast<const char*>(data);
    std::copy(d, d+len, begin()+readerIndex_);//将源数据范围[d, d+len)的字节复制到目标缓冲区。
}

/* 收缩缓冲区空间, 将缓冲区中数据拷贝到新缓冲区, 确保writable空间最终大小为reserve */
void MsgBuffer::shrink(size_t reserve)
{
    // FIXME: use vector::shrink_to_fit() in C++ 11 if possible.
    // MsgBuffer other;
    // other.ensureWritableBytes(readableBytes() + reserve);
    // other.append(toStringPiece());
    // swap(other);
}

size_t MsgBuffer::internalCapacity() const
{
    return buffer_.capacity();
} 

void MsgBuffer::makeSpace(size_t len)
{
    if (writableBytes() + prependableBytes() < len + kCheapPrepend)
    {   // writable 空间大小 + prependable空间大小 不足以存放len byte数据, resize内部缓冲区大小
        // FIXME: move readable data
        buffer_.resize(writerIndex_ + len);
    }
    else
    { // writable 空间大小 + prependable空间大小 足以存放len byte数据, 移动readable空间数据, 合并多余prependable空间到writable空间
        assert(kCheapPrepend < readerIndex_);
        size_t readable = readableBytes();
        std::copy(begin() + readerIndex_,
                    begin() + writerIndex_,
                    begin() + kCheapPrepend);
        readerIndex_ = kCheapPrepend;
        writerIndex_ = readerIndex_ + readable;
        assert(readable == readableBytes());
    }
}

ssize_t MsgBuffer::readFd(int fd, int* savedErrno)
{
    /*将主缓冲区的可写部分（vec[0]）和额外缓冲区（vec[1]）组合成一个 iovec数组，用于高效执行分散写入（writev）或分散读取（readv）操作。*/
    char extrabuf[65536]; // 65536 = 64K bytes
    struct iovec vec[2];
    const size_t writable = writableBytes();
    vec[0].iov_base = begin() + writerIndex_;
    vec[0].iov_len = writable;

    vec[1].iov_base = extrabuf;
    vec[1].iov_len = sizeof(extrabuf);

    // 根据内部空间剩余量选择缓冲区数量
    const int iovcnt = (writable < sizeof(extrabuf)) ? 2 : 1;//指定 vec数组中有效元素的个数
    const ssize_t n =  ::readv(fd, vec, iovcnt);
    if (n < 0)
    { // ::readv系统调用错误
       *savedErrno = errno;
    }
    else if (static_cast<size_t>(n)  <= writable)
    {
        writerIndex_ += n;
    }
    else
    {
        // 读取的数据超过现有内部buffer_的writable空间大小时, 启用备用的extrabuf 64KB空间, 并将这些数据添加到内部buffer_的末尾
        // 过程可能会合并多余prependable空间或resize buffer_大小, 以腾出足够writable空间存放数据
        writerIndex_ = buffer_.size();
        append(extrabuf, n - writable);
    }
    return n;
}


const char* MsgBuffer::findCRLF() const
{
    // FIXME: replace with memmem()?
    const char* crlf = std::search(peek(), beginWrite(), kCRLF, kCRLF+2);
    return crlf == beginWrite() ? NULL : crlf;
}

const char* MsgBuffer::findCRLF(const char* start) const
{
    assert(peek() <= start);
    assert(start <= beginWrite());
    // FIXME: replace with memmem()?
    const char* crlf = std::search(start, beginWrite(), kCRLF, kCRLF+2);
    return crlf == beginWrite() ? NULL : crlf;
}

const char* MsgBuffer::findEOL() const
{
    const void* eol = memchr(peek(), '\n', readableBytes());
    return static_cast<const char*>(eol);
}

const char* MsgBuffer::findEOL(const char* start) const
{
    assert(peek() <= start);
    assert(start <= beginWrite());
    const void* eol = memchr(start, '\n', beginWrite() - start);
    return static_cast<const char*>(eol);
}

